/*
 * File:   Graph.cpp
 *
 * Created on 18 octobre 2011, 11:19
 * Authors: bnoleau, cybourdi, rlecrois
 */

#include "Graph.h"
#include "strategy/Strategy.h"

Graph::Graph(int n) {
	vertices = new vector<Node*>();
	for (int i = 0; i < n; i++)
		addNode(new Node(i+1));
}

Graph::~Graph() {
}

Node* Graph::nodeAt(int i) {
	return getVertices()->at(i);
}

void Graph::addNode(Node* n) {
	if (numberOfNode() <  n->getID())
		getVertices()->push_back(n);
}

vector<Node*>* Graph::getVertices() {
	return vertices;
}

void Graph::createEdge(Node* n1, Node* n2) {
	n1->addEdge(n2);
}

int Graph::numberOfEdge(){
	int nbEdge = 0;
    for (int i = 0; i < numberOfNode(); i++)
			nbEdge+= nodeAt(i)->outDeg();

	return (nbEdge/2);
}

int Graph::numberOfNode(){
	return getVertices()->size();
}

list<int> Graph::launchVertexCover(){
	list<int> cover;
	if ( strategy != NULL)	
		cover = strategy->vertexCover(this);
		
	return cover;
}

void Graph::setStrategy(Strategy *newStrategy){
	strategy = newStrategy;
}

bool Graph::hasLeaf() {
	bool hasLeaf = false;

	for (int i = 0; i < numberOfNode(); i++)
		if (nodeAt(i)->isLeaf())
			hasLeaf = true;

	return hasLeaf;
}

Node* Graph::getFatherOfLeaf(){
	 for (int i = 0; i < numberOfNode(); i++)
		for (list<Node*>::iterator it = nodeAt(i)->getEdgeList()->begin(); it != nodeAt(i)->getEdgeList()->end(); ++it)
			if ((*it)->isLeaf())
				return nodeAt(i);
	
	return NULL;
}

void Graph::eraseEdgesOfNode(Node* n) {
	for (list<Node*>::iterator it = n->getEdgeList()->begin(); it != n->getEdgeList()->end(); ++it)
			removeNodeFromList(n, (*it)->getEdgeList());
	n->getEdgeList()->clear();
}

void Graph::removeNodeFromList(Node* node, list<Node*> *listnode) {
	for (list<Node*>::iterator it = listnode->begin(); it != listnode->end();) {
		if ((*it)->getID() == node->getID()) {
			listnode->erase(it);
			break;
		} else
			++it;
	}
}

void Graph::build(Builder *b){

	b->beginGraph(numberOfNode(), numberOfEdge());
	for (int i = 0 ; i < numberOfNode() ; i++)
		nodeAt(i)->build(b);

	b->endGraph();
}

void Graph::toString(ostream &flux) {
        for (int i = 0; i < numberOfNode(); i++)
		flux << *(getVertices()->at(i)) << endl;
}

ostream &operator<<(ostream &flux, Graph& graph) {
	graph.toString(flux);
	return flux;
}
